#include "h_stm32_hal_uart.h"
#include "h_stm32_hal_defines.h"
#include <stdio.h>
#include <string.h>
/*
	For some reason, f0xx series chip use different register
*/
#define H_STM32_UART_0XX					1

static UART_HandleTypeDef *print_uart = NULL;
#define UART_PRINT_TIMEOUT					0xFFFF

#ifdef __GNUC__  
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)  
#else  
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)  
#endif /* __GNUC__ */  

PUTCHAR_PROTOTYPE  
{  
	if(NULL != print_uart) {
		HAL_UART_Transmit(print_uart , (uint8_t *)&ch, 1, UART_PRINT_TIMEOUT);
	}
    return ch;  
}  

int _write(int file, char *ptr, int len)
{
  int DataIdx;

    for (DataIdx = 0; DataIdx < len; DataIdx++)
    {
       __io_putchar( *ptr++ );
    }
  return len;
}


void h_stm32_hal_uart_printf_init(UART_HandleTypeDef *handle)
{
	print_uart = handle;
}

h_stm32_hal_uart_t h_stm32_hal_uart_init(UART_HandleTypeDef *handle, \
	h_stm32_hal_uart_state rxEnable, DMA_HandleTypeDef *dma, \
	unsigned short rxlen, void *callback)
{
	h_stm32_hal_uart_t uart_t;
	uart_t.uartHandle = handle;
	if(h_stm32_hal_uart_enable == rxEnable) {
		uart_t.uartRxDMA = dma;
		uart_t.rxDMAEnable = rxEnable;
		// uart_t.rxBuffer = (unsigned char *)H_STM32_MALLOC(sizeof(unsigned char) * rxLength);
		// if(NULL == uart_t.rxBuffer) {
		// 	uart_t.rxLength = 0U;
		// 	return NULL;
		// }
		uart_t.rxLength = rxlen;
		uart_t.receiveCallback = callback;
	}
	return uart_t;
}

h_stm32_hal_uart_state h_stm32_hal_uart_startReceive(h_stm32_hal_uart_t *uart_t)
{
	if(h_stm32_hal_uart_enable != uart_t->rxDMAEnable) {
		return h_stm32_hal_uart_disable;
	}
	uart_t->rxBuffer = (unsigned char *)H_STM32_MALLOC(sizeof(unsigned char) * uart_t->rxLength);
	if(NULL == uart_t->rxBuffer) {
		return h_stm32_hal_uart_malloc_failed;
	}

	__HAL_UART_ENABLE_IT(uart_t->uartHandle, UART_IT_IDLE);
	HAL_UART_Receive_DMA(uart_t->uartHandle, uart_t->rxBuffer, uart_t->rxLength);

	return h_stm32_hal_uart_ok;
}

h_stm32_hal_uart_state h_stm32_hal_uart_handleReceive(h_stm32_hal_uart_t *uart_t)
{
	unsigned int tmp_flag = 0;
	unsigned int temp;
	unsigned short dataRealLength;

	if(h_stm32_hal_uart_enable != uart_t->rxDMAEnable) {
		return h_stm32_hal_uart_disable;
	}

	tmp_flag =__HAL_UART_GET_FLAG(uart_t->uartHandle, UART_FLAG_IDLE);

	if((tmp_flag != RESET)) {

		__HAL_UART_CLEAR_IDLEFLAG(uart_t->uartHandle);
#if H_STM32_UART_0XX
		temp = uart_t->uartHandle->Instance->ISR;  //CLear ISR register
		temp = uart_t->uartHandle->Instance->RDR;  //Clear RDR register
		HAL_UART_DMAStop(uart_t->uartHandle); //
		temp  = uart_t->uartRxDMA->Instance->CNDTR; // Get the data space left
#else
		temp = uart_t->uartHandle->Instance->SR;  //CLear ISR register
		temp = uart_t->uartHandle->Instance->DR;  //Clear RDR register
		HAL_UART_DMAStop(uart_t->uartHandle); //
		temp  = uart_t->uartRxDMA->Instance->NDTR; // Get the data space left
#endif
		dataRealLength =  uart_t->rxLength - temp;  //Get the real data
		// Callback handle
		if(dataRealLength < uart_t->rxLength && dataRealLength > 0) {
			uart_t->receiveCallback(uart_t->rxBuffer, dataRealLength);
		}
		
		HAL_UART_Receive_DMA(uart_t->uartHandle, uart_t->rxBuffer, uart_t->rxLength);
	}
	return h_stm32_hal_uart_ok;
}

#define STR2HEX_LEN     128
void str2hex(unsigned char *pAddr, unsigned short len, unsigned char *str2hexdata)
{
  unsigned short     charCnt;
  const unsigned char        hex[] = "0123456789ABCDEF";
  unsigned char        *pStr = str2hexdata;

  for (charCnt = 0; charCnt < len; charCnt++)
  {
    *pStr++ = hex[*pAddr >> 4];
    *pStr++ = hex[*pAddr++ & 0x0F];
  }

  *pStr = '\0';

  pStr = NULL;
}



void debug_hex(unsigned char *data, unsigned short len)
{
  unsigned short i = 0;
  unsigned short d_len = 0;

  unsigned char *tdata = data;

  unsigned char str2hexdata[STR2HEX_LEN + STR2HEX_LEN + 1];

  for(i = 0; i <= len; i += STR2HEX_LEN)
  {
    d_len = len < STR2HEX_LEN ? len : STR2HEX_LEN;

    str2hex(tdata, d_len, &str2hexdata[0]);

    printf("%s", &str2hexdata[0]);

    if(len < STR2HEX_LEN)
    {
      break;
    }

    len -= STR2HEX_LEN;
    tdata += STR2HEX_LEN;
  }


  printf("\r\n");
}
